home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Astrolog (Version 4.40) File: matrix.c
- **
- ** IMPORTANT NOTICE: The graphics database and chart display routines
- ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
- ** (astara@u.washington.edu). Permission is granted to freely use and
- ** distribute these routines provided one doesn't sell, restrict, or
- ** profit from them in any way. Modification is allowed provided these
- ** notices remain with any altered or edited versions of the program.
- **
- ** The main planetary calculation routines used in this program have
- ** been Copyrighted and the core of this program is basically a
- ** conversion to C of the routines created by James Neely as listed in
- ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
- ** available from Matrix Software. The copyright gives us permission to
- ** use the routines for personal use but not to sell them or profit from
- ** them in any way.
- **
- ** The PostScript code within the core graphics routines are programmed
- ** and Copyright (C) 1992-1993 by Brian D. Willoughby
- ** (brianw@sounds.wa.com). Conditions are identical to those above.
- **
- ** The extended accurate ephemeris databases and formulas are from the
- ** calculation routines in the program "Placalc" and are programmed and
- ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
- ** (alois@azur.ch). The use of that source code is subject to
- ** regulations made by Astrodienst Zurich, and the code is not in the
- ** public domain. This copyright notice must not be changed or removed
- ** by any user of this program.
- **
- ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
- ** X Window graphics initially programmed 10/23-29/1991.
- ** PostScript graphics initially programmed 11/29-30/1992.
- ** Last code change made 1/29/1995.
- */
-
- #include "astrolog.h"
-
-
- #ifdef MATRIX
- real MC, Asc, RA, OB;
-
-
- /*
- ******************************************************************************
- ** Assorted Calculations.
- ******************************************************************************
- */
-
- /* Given a month, day, and year, convert it into a single Julian day value, */
- /* i.e. the number of days passed since a fixed reference date. */
-
- long MdyToJulian(mon, day, yea)
- int mon, day, yea;
- {
- #ifndef PLACALC
- long im, j;
-
- im = 12*((long)yea+4800)+(long)mon-3;
- j = (2*(im%12) + 7 + 365*im)/12;
- j += (long)day + im/48 - 32083;
- if (j > 2299171) /* Take care of dates in */
- j += im/4800 - im/1200 + 38; /* Gregorian calendar. */
- return j;
- #else
- int fGreg = fTrue;
-
- if (yea < yeaJ2G || (yea == yeaJ2G &&
- (mon < monJ2G || (mon == monJ2G && day < 15))))
- fGreg = fFalse;
- return (long)RFloor(julday(mon, day, yea, 12.0, fGreg)+rRound);
- #endif
- }
-
-
- /* Like above but return a fractional Julian time given the extra info. */
-
- real MdytszToJulian(mon, day, yea, tim, dst, zon)
- int mon, day, yea;
- real tim, dst, zon;
- {
- return (real)MdyToJulian(mon, day, yea) +
- (DecToDeg(tim) + DecToDeg(zon) - DecToDeg(dst)) / 24.0;
- }
-
-
- /* Take a Julian day value, and convert it back into the corresponding */
- /* month, day, and year. */
-
- void JulianToMdy(JD, mon, day, yea)
- real JD;
- int *mon, *day, *yea;
- {
- #ifndef PLACALC
- long L, N, IT, JT, K, IK;
-
- L = (long)RFloor(JD+rRound)+68569L;
- N = Dvd(4L*L, 146097L);
- L -= Dvd(146097L*N + 3L, 4L);
- IT = Dvd(4000L*(L+1L), 1461001L);
- L -= Dvd(1461L*IT, 4L) - 31L;
- JT = Dvd(80L*L, 2447L);
- K = L-Dvd(2447L*JT, 80L);
- L = Dvd(JT, 11L);
- JT += 2L - 12L*L;
- IK = 100L*(N-49L) + IT + L;
- *mon = (int)JT; *day = (int)K; *yea = (int)IK;
- #else
- double tim;
-
- revjul(JD, JD >= 2299171.0 /* October 15, 1582 */, mon, day, yea, &tim);
- #endif
- }
-
-
- /* This is a subprocedure of CastChart(). Once we have the chart parameters, */
- /* calculate a few important things related to the date, i.e. the Greenwich */
- /* time, the Julian day and fractional part of the day, the offset to the */
- /* sidereal, and a couple of other things. */
-
- real ProcessInput(fDate)
- bool fDate;
- {
- real Off, Ln;
-
- TT = RSgn(TT)*RFloor(RAbs(TT))+RFract(RAbs(TT))*100.0/60.0 +
- (DecToDeg(ZZ) - DecToDeg(SS));
- OO = DecToDeg(OO);
- AA = Min(AA, 89.9999); /* Make sure the chart isn't being cast */
- AA = Max(AA, -89.9999); /* on the precise north or south pole. */
- AA = RFromD(DecToDeg(AA));
-
- /* if parameter 'fDate' isn't set, then we can assume that the true time */
- /* has already been determined (as in a -rm switch time midpoint chart). */
-
- if (fDate) {
- is.JD = (real)MdyToJulian(MM, DD, YY);
- if (!us.fProgress || us.fSolarArc)
- T = (is.JD + TT/24.0 - 2415020.5) / 36525.0;
- else {
- /* Determine actual time that a progressed chart is to be cast for. */
-
- T = ((is.JD + TT/24.0 + (is.JDp - (is.JD + TT/24.0)) / us.rProgDay) -
- 2415020.5) / 36525.0;
- }
- }
-
- /* Compute angle that the ecliptic is inclined to the Celestial Equator */
- OB = RFromD(23.452294-0.0130125*T);
-
- Ln = Mod((933060-6962911*T+7.5*T*T)/3600.0); /* Mean lunar node */
- Off = (259205536.0*T+2013816.0)/3600.0; /* Mean Sun */
- Off = 17.23*RSin(RFromD(Ln))+1.27*RSin(RFromD(Off))-(5025.64+1.11*T)*T;
- Off = (Off-84038.27)/3600.0;
- is.rSid = (us.fSiderial ? Off : 0.0) + us.rZodiacOffset;
- return Off;
- }
-
-
- /* Convert polar to rectangular coordinates. */
-
- void PolToRec(A, R, X, Y)
- real A, R, *X, *Y;
- {
- if (A == 0.0)
- A = rSmall;
- *X = R*RCos(A);
- *Y = R*RSin(A);
- }
-
-
- /* Convert rectangular to polar coordinates. */
-
- void RecToPol(X, Y, A, R)
- real X, Y, *A, *R;
- {
- if (Y == 0.0)
- Y = rSmall;
- *R = RSqr(X*X + Y*Y);
- *A = Angle(X, Y);
- }
-
-
- /* Convert rectangular to spherical coordinates. */
-
- real RecToSph(B, L, O)
- real B, L, O;
- {
- real R, Q, G, X, Y, A;
-
- A = B; R = 1.0;
- PolToRec(A, R, &X, &Y);
- Q = Y; R = X; A = L;
- PolToRec(A, R, &X, &Y);
- G = X; X = Y; Y = Q;
- RecToPol(X, Y, &A, &R);
- A += O;
- PolToRec(A, R, &X, &Y);
- Q = RAsin(Y);
- Y = X; X = G;
- RecToPol(X, Y, &A, &R);
- if (A < 0.0)
- A += 2*rPi;
- G = A;
- return G; /* We only ever care about and return one of the coordinates. */
- }
-
-
- /* Do a coordinate transformation: Given a longitude and latitude value, */
- /* return the new longitude and latitude values that the same location */
- /* would have, were the equator tilted by a specified number of degrees. */
- /* In other words, do a pole shift! This is used to convert among ecliptic, */
- /* equatorial, and local coordinates, each of which have zero declination */
- /* in different planes. In other words, take into account the Earth's axis. */
-
- void CoorXform(azi, alt, tilt)
- real *azi, *alt, tilt;
- {
- real x, y, a1, l1;
- real sinalt, cosalt, sinazi, sintilt, costilt;
-
- sinalt = RSin(*alt); cosalt = RCos(*alt); sinazi = RSin(*azi);
- sintilt = RSin(tilt); costilt = RCos(tilt);
-
- x = cosalt * sinazi * costilt;
- y = sinalt * sintilt;
- x -= y;
- a1 = cosalt;
- y = cosalt * RCos(*azi);
- l1 = Angle(y, x);
- a1 = a1 * sinazi * sintilt + sinalt * costilt;
- a1 = RAsin(a1);
- *azi = l1; *alt = a1;
- }
-
-
- /* This is another subprocedure of CastChart(). Calculate a few variables */
- /* corresponding to the chart parameters that are used later on. The */
- /* astrological vertex (object number twenty) is also calculated here. */
-
- void ComputeVariables(vtx)
- real *vtx;
- {
- real R, R2, B, L, O, G, X, Y, A;
-
- RA = RFromD(Mod((6.6460656+2400.0513*T+2.58E-5*T*T+TT)*15.0-OO));
- R2 = RA; O = -OB; B = AA; A = R2; R = 1.0;
- PolToRec(A, R, &X, &Y);
- X *= RCos(O);
- RecToPol(X, Y, &A, &R);
- MC = Mod(is.rSid + DFromR(A)); /* Midheaven */
- #if FALSE
- L = R2;
- G = RecToSph(B, L, O);
- Asc = Mod(is.rSid + Mod(G+rPiHalf)); /* Ascendant */
- #endif
- L= R2+rPi; B = rPiHalf-RAbs(B);
- if (AA < 0.0)
- B = -B;
- G = RecToSph(B, L, O);
- *vtx = Mod(is.rSid + DFromR(G+rPiHalf)); /* Vertex */
- }
-
-
- /*
- ******************************************************************************
- ** House Cusp Calculations.
- ******************************************************************************
- */
-
- /* The following three functions calculate the Midheaven, Ascendant, and */
- /* East Point of the chart in question, based on time and location. The */
- /* first two are also used in some of the house cusp calculation routines */
- /* as a quick way to get the 10th and 1st cusps. The East Point object is */
- /* technically defined as the Ascendant's position at zero latitude. */
-
- real CuspMidheaven()
- {
- real MC;
-
- MC = RAtn(RTan(RA)/RCos(OB));
- if (MC < 0.0)
- MC += rPi;
- if (RA > rPi)
- MC += rPi;
- return Mod(DFromR(MC)+is.rSid);
- }
-
- real CuspAscendant()
- {
- real Asc;
-
- Asc = Angle(-RSin(RA)*RCos(OB)-RTan(AA)*RSin(OB), RCos(RA));
- return Mod(DFromR(Asc)+is.rSid);
- }
-
- real CuspEastPoint()
- {
- real EP;
-
- EP = Angle(-RSin(RA)*RCos(OB), RCos(RA));
- return Mod(DFromR(EP)+is.rSid);
- }
-
-
- /* These are various different algorithms for calculating the house cusps: */
-
- real CuspPlacidus(deg, FF, fNeg)
- real deg, FF;
- bool fNeg;
- {
- real LO, R1, XS, X;
- int i;
-
- R1 = RA+RFromD(deg);
- X = fNeg ? 1.0 : -1.0;
- /* Looping 10 times is arbitrary, but it's what other programs do. */
- for (i = 1; i <= 10; i++) {
-
- /* This formula works except at 0 latitude (AA == 0.0). */
-
- XS = X*RSin(R1)*RTan(OB)*RTan(AA == 0.0 ? 0.0001 : AA);
- XS = RAcos(XS);
- if (XS < 0.0)
- XS += rPi;
- R1 = RA + (fNeg ? rPi-(XS/FF) : (XS/FF));
- }
- LO = RAtn(RTan(R1)/RCos(OB));
- if (LO < 0.0)
- LO += rPi;
- if (RSin(R1) < 0.0)
- LO += rPi;
- return DFromR(LO);
- }
-
- void HousePlacidus()
- {
- int i;
-
- house[1] = Mod(Asc-is.rSid);
- house[4] = Mod(MC+rDegHalf-is.rSid);
- house[5] = CuspPlacidus(30.0, 3.0, fFalse) + rDegHalf;
- house[6] = CuspPlacidus(60.0, 1.5, fFalse) + rDegHalf;
- house[2] = CuspPlacidus(120.0, 1.5, fTrue);
- house[3] = CuspPlacidus(150.0, 3.0, fTrue);
- for (i = 1; i <= cSign; i++) {
- if (i <= 6)
- house[i] = Mod(house[i]+is.rSid);
- else
- house[i] = Mod(house[i-6]+rDegHalf);
- }
- }
-
- void HouseKoch()
- {
- real A1, A2, A3, KN, D, X;
- int i;
-
- A1 = RSin(RA)*RTan(AA)*RTan(OB);
- A1 = RAsin(A1);
- for (i = 1; i <= cSign; i++) {
- D = Mod(60.0+30.0*(real)i);
- A2 = D/rDegQuad-1.0; KN = 1.0;
- if (D >= rDegHalf) {
- KN = -1.0;
- A2 = D/rDegQuad-3.0;
- }
- A3 = RFromD(Mod(DFromR(RA)+D+A2*DFromR(A1)));
- X = Angle(RCos(A3)*RCos(OB)-KN*RTan(AA)*RSin(OB), RSin(A3));
- house[i] = Mod(DFromR(X)+is.rSid);
- }
- }
-
- void HouseEqual()
- {
- int i;
-
- for (i = 1; i <= cSign; i++)
- house[i] = Mod(Asc-30.0+30.0*(real)i);
- }
-
- void HouseCampanus()
- {
- real KO, DN, X;
- int i;
-
- for (i = 1; i <= cSign; i++) {
- KO = RFromD(60.000001+30.0*(real)i);
- DN = RAtn(RTan(KO)*RCos(AA));
- if (DN < 0.0)
- DN += rPi;
- if (RSin(KO) < 0.0)
- DN += rPi;
- X = Angle(RCos(RA+DN)*RCos(OB)-RSin(DN)*RTan(AA)*RSin(OB), RSin(RA+DN));
- house[i] = Mod(DFromR(X)+is.rSid);
- }
- }
-
- void HouseMeridian()
- {
- real D, X;
- int i;
-
- for (i = 1; i <= cSign; i++) {
- D = RFromD(60.0+30.0*(real)i);
- X = Angle(RCos(RA+D)*RCos(OB), RSin(RA+D));
- house[i] = Mod(DFromR(X)+is.rSid);
- }
- }
-
- void HouseRegiomontanus()
- {
- real D, X;
- int i;
-
- for (i = 1; i <= cSign; i++) {
- D = RFromD(60.0+30.0*(real)i);
- X = Angle(RCos(RA+D)*RCos(OB)-RSin(D)*RTan(AA)*RSin(OB), RSin(RA+D));
- house[i] = Mod(DFromR(X)+is.rSid);
- }
- }
-
- void HousePorphyry()
- {
- real X, Y;
- int i;
-
- X = Asc-MC;
- if (X < 0.0)
- X += rDegMax;
- Y = X/3.0;
- for (i = 1; i <= 2; i++)
- house[i+4] = Mod(rDegHalf+MC+i*Y);
- X = Mod(rDegHalf+MC)-Asc;
- if (X < 0.0)
- X += rDegMax;
- house[1]=Asc;
- Y = X/3.0;
- for (i = 1; i <= 3; i++)
- house[i+1] = Mod(Asc+i*Y);
- for (i = 1; i <= 6; i++)
- house[i+6] = Mod(house[i]+rDegHalf);
- }
-
- void HouseMorinus()
- {
- real D, X;
- int i;
-
- for (i = 1; i <= cSign; i++) {
- D = RFromD(60.0+30.0*(real)i);
- X = Angle(RCos(RA+D), RSin(RA+D)*RCos(OB));
- house[i] = Mod(DFromR(X)+is.rSid);
- }
- }
-
- real CuspTopocentric(deg)
- real deg;
- {
- real OA, X, LO;
-
- OA = ModRad(RA+RFromD(deg));
- X = RAtn(RTan(AA)/RCos(OA));
- LO = RAtn(RCos(X)*RTan(OA)/RCos(X+OB));
- if (LO < 0.0)
- LO += rPi;
- if (RSin(OA) < 0.0)
- LO += rPi;
- return LO;
- }
-
- void HouseTopocentric()
- {
- real TL, P1, P2, LT;
- int i;
-
- house[4] = ModRad(RFromD(MC+rDegHalf-is.rSid));
- TL = RTan(AA); P1 = RAtn(TL/3.0); P2 = RAtn(TL/1.5); LT = AA;
- AA = P1; house[5] = CuspTopocentric(30.0) + rPi;
- AA = P2; house[6] = CuspTopocentric(60.0) + rPi;
- AA = LT; house[1] = CuspTopocentric(90.0);
- AA = P2; house[2] = CuspTopocentric(120.0);
- AA = P1; house[3] = CuspTopocentric(150.0);
- AA = LT;
- for (i = 1; i <= 6; i++) {
- house[i] = Mod(DFromR(house[i])+is.rSid);
- house[i+6] = Mod(house[i]+rDegHalf);
- }
- }
-
-
- /*
- ******************************************************************************
- ** Planetary Position Calculations.
- ******************************************************************************
- */
-
- /* Given three values, return them combined as the coefficients of a */
- /* quadratic equation as a function of the chart time. */
-
- real ReadThree(r0, r1, r2)
- real r0, r1, r2;
- {
- return RFromD(r0 + r1*T + r2*T*T);
- }
-
-
- /* Another coordinate transformation. This is used by the ComputePlanets() */
- /* procedure to rotate rectangular coordinates by a certain amount. */
-
- void RecToSph2(AP, AN, IN, X, Y, G)
- real AP, AN, IN, *X, *Y, *G;
- {
- real R, D, A;
-
- RecToPol(*X, *Y, &A, &R); A += AP; PolToRec(A, R, X, Y);
- D = *X; *X = *Y; *Y = 0.0; RecToPol(*X, *Y, &A, &R);
- A += IN; PolToRec(A, R, X, Y);
- *G = *Y; *Y = *X; *X = D; RecToPol(*X, *Y, &A, &R); A += AN;
- if (A < 0.0)
- A += 2.0*rPi;
- PolToRec(A, R, X, Y);
- }
-
-
- /* Calculate some harmonic delta error correction factors to add onto the */
- /* coordinates of Jupiter through Pluto, for better accuracy. */
-
- void ErrorCorrect(ind, x, y, z)
- int ind;
- real *x, *y, *z;
- {
- real U, V, W, A, S0, T0[4], FAR *pr;
- int IK, IJ, irError;
-
- irError = errorcount[ind-oJup];
- pr = (lpreal)&errordata[erroroffset[ind-oJup]];
- for (IK = 1; IK <= 3; IK++) {
- if (ind == oJup && IK == 3) {
- T0[3] = 0.0;
- break;
- }
- if (IK == 3)
- irError--;
- S0 = ReadThree(pr[0], pr[1], pr[2]); pr += 3;
- A = 0.0;
- for (IJ = 1; IJ <= irError; IJ++) {
- U = *pr++; V = *pr++; W = *pr++;
- A += RFromD(U)*RCos((V*T+W)*rPi/rDegHalf);
- }
- T0[IK] = DFromR(S0+A);
- }
- *x += T0[2]; *y += T0[1]; *z += T0[3];
- }
-
-
- /* Another subprocedure of the ComputePlanets() routine. Convert the final */
- /* rectangular coordinates of a planet to zodiac position and declination. */
-
- void ProcessPlanet(ind, aber)
- int ind;
- real aber;
- {
- real ang, rad;
-
- RecToPol(spacex[ind], spacey[ind], &ang, &rad);
- planet[ind] = Mod(DFromR(ang) /*+ NU*/ - aber + is.rSid);
- RecToPol(rad, spacez[ind], &ang, &rad);
- if (us.objCenter == oSun && ind == oSun)
- ang = 0.0;
- ang = DFromR(ang);
- while (ang > rDegQuad) /* Ensure declination is from -90..+90 degrees. */
- ang -= rDegHalf;
- while (ang < -rDegQuad)
- ang += rDegHalf;
- planetalt[ind] = ang;
- }
-
-
- /* This is probably the heart of the whole program of Astrolog. Calculate */
- /* the position of each body that orbits the Sun. A heliocentric chart is */
- /* most natural; extra calculation is needed to have other central bodies. */
-
- void ComputePlanets()
- {
- real helio[oNorm+1], helioalt[oNorm+1], helioret[oNorm+1],
- heliox[oNorm+1], helioy[oNorm+1], helioz[oNorm+1];
- real aber = 0.0, AU, E, EA, E1, M, XW, YW, AP, AN, IN, X, Y, G, XS, YS, ZS;
- int ind = oSun, i;
- OE *poe;
-
- while (ind <= (us.fUranian ? oNorm : cPlanet)) {
- if (ignore[ind] && ind > oSun)
- goto LNextPlanet;
- poe = &rgoe[IoeFromObj(ind)];
-
- EA = M = ModRad(ReadThree(poe->ma0, poe->ma1, poe->ma2));
- E = DFromR(ReadThree(poe->ec0, poe->ec1, poe->ec2));
- for (i = 1; i <= 5; i++)
- EA = M+E*RSin(EA); /* Solve Kepler's equation */
- AU = poe->sma; /* Semi-major axis */
- E1 = 0.01720209/(pow(AU, 1.5)*
- (1.0-E*RCos(EA))); /* Begin velocity coordinates */
- XW = -AU*E1*RSin(EA); /* Perifocal coordinates */
- YW = AU*E1*pow(1.0-E*E,0.5)*RCos(EA);
- AP = ReadThree(poe->ap0, poe->ap1, poe->ap2);
- AN = ReadThree(poe->an0, poe->an1, poe->an2);
- IN = ReadThree(poe->in0, poe->in1, poe->in2); /* Calculate inclination */
- X = XW; Y = YW;
- RecToSph2(AP, AN, IN, &X, &Y, &G); /* Rotate velocity coords */
- heliox[ind] = X; helioy[ind] = Y;
- helioz[ind] = G; /* Helio ecliptic rectangtular */
- X = AU*(RCos(EA)-E); /* Perifocal coordinates for */
- Y = AU*RSin(EA)*pow(1.0-E*E,0.5); /* rectangular position coordinates */
- RecToSph2(AP, AN, IN, &X, &Y, &G); /* Rotate for rectangular */
- XS = X; YS = Y; ZS = G; /* position coordinates */
- if (FBetween(ind, oJup, oPlu))
- ErrorCorrect(ind, &XS, &YS, &ZS);
- ret[ind] = /* Helio daily motion */
- (XS*helioy[ind]-YS*heliox[ind])/(XS*XS+YS*YS);
- spacex[ind] = XS; spacey[ind] = YS; spacez[ind] = ZS;
- ProcessPlanet(ind, 0.0);
- LNextPlanet:
- ind += (ind == oSun ? 2 : (ind != cPlanet ? 1 : uranLo-cPlanet));
- }
- spacex[0] = spacey[0] = spacez[0] = 0.0;
-
- if (!us.objCenter) {
- if (us.fVelocity)
- for (i = 0; i <= oNorm; i++) /* Use relative velocity */
- ret[i] = RFromD(1.0); /* if -v0 is in effect. */
- return;
- }
- #endif /* MATRIX */
-
- /* A second loop is needed for geocentric charts or central bodies other */
- /* than the Sun. For example, we can't find the position of Mercury in */
- /* relation to Pluto until we know the position of Pluto in relation to */
- /* the Sun, and since Mercury is calculated first, another pass needed. */
-
- ind = us.objCenter;
- for (i = 0; i <= oNorm; i++) {
- helio[i] = planet[i];
- helioalt[i] = planetalt[i];
- helioret[i] = ret[i];
- if (i != oMoo && i != ind) {
- spacex[i] -= spacex[ind];
- spacey[i] -= spacey[ind];
- spacez[i] -= spacez[ind];
- }
- }
- spacex[ind] = spacey[ind] = spacez[ind] = 0.0;
- SwapR(&spacex[0], &spacex[ind]);
- SwapR(&spacey[0], &spacey[ind]); /* Do some swapping - we want */
- SwapR(&spacez[0], &spacez[ind]); /* the central body to be in */
- SwapR(&spacex[1], &spacex[ind]); /* object position number zero. */
- SwapR(&spacey[1], &spacey[ind]);
- SwapR(&spacez[1], &spacez[ind]);
- for (i = 1; i <= (us.fUranian ? oNorm : cPlanet);
- i += (i == 1 ? 2 : (i != cPlanet ? 1 : uranLo-cPlanet))) {
- if (ignore[i] && i > oSun)
- continue;
- XS = spacex[i]; YS = spacey[i]; ZS = spacez[i];
- if (ind != oSun || i != oSun)
- ret[i] = (XS*(helioy[i]-helioy[ind])-YS*(heliox[i]-heliox[ind]))/
- (XS*XS+YS*YS);
- if (ind == oSun)
- aber = 0.0057756*RSqr(XS*XS+YS*YS+ZS*ZS)*DFromR(ret[i]); /* Aberration */
- ProcessPlanet(i, aber);
- if (us.fVelocity) /* Use relative velocity */
- ret[i] = RFromD(ret[i]/helioret[i]); /* if -v0 is in effect */
- }
- }
-
-
- #ifdef MATRIX
- /*
- ******************************************************************************
- ** Lunar Position Calculations
- ******************************************************************************
- */
-
- /* Calculate the position and declination of the Moon, and the Moon's North */
- /* Node. This has to be done separately from the other planets, because they */
- /* all orbit the Sun, while the Moon orbits the Earth. */
-
- void ComputeLunar(moonlo, moonla, nodelo, nodela)
- real *moonlo, *moonla, *nodelo, *nodela;
- {
- real LL, G, N, G1, D, L, ML, L1, MB, T1, Y, M = 3600.0;
-
- LL = 973563.0+1732564379.0*T-4.0*T*T; /* Compute mean lunar longitude */
- G = 1012395.0+6189.0*T; /* Sun's mean longitude of perigee */
- N = 933060.0-6962911.0*T+7.5*T*T; /* Compute mean lunar node */
- G1 = 1203586.0+14648523.0*T-37.0*T*T; /* Mean longitude of lunar perigee */
- D = 1262655.0+1602961611.0*T-5.0*T*T; /* Mean elongation of Moon from Sun */
- L = (LL-G1)/M; L1 = ((LL-D)-G)/M; /* Some auxiliary angles */
- T1 = (LL-N)/M; D = D/M; Y = 2.0*D;
-
- /* Compute Moon's perturbations. */
-
- ML = 22639.6*RSinD(L) - 4586.4*RSinD(L-Y) + 2369.9*RSinD(Y) +
- 769.0*RSinD(2.0*L) - 669.0*RSinD(L1) - 411.6*RSinD(2.0*T1) -
- 212.0*RSinD(2.0*L-Y) - 206.0*RSinD(L+L1-Y);
- ML += 192.0*RSinD(L+Y) - 165.0*RSinD(L1-Y) + 148.0*RSinD(L-L1) -
- 125.0*RSinD(D) - 110.0*RSinD(L+L1) - 55.0*RSinD(2.0*T1-Y) -
- 45.0*RSinD(L+2.0*T1) + 40.0*RSinD(L-2.0*T1);
-
- *moonlo = G = Mod((LL+ML)/M+is.rSid); /* Lunar longitude */
-
- /* Compute lunar latitude. */
-
- MB = 18461.5*RSinD(T1) + 1010.0*RSinD(L+T1) - 999.0*RSinD(T1-L) -
- 624.0*RSinD(T1-Y) + 199.0*RSinD(T1+Y-L) - 167.0*RSinD(L+T1-Y);
- MB += 117.0*RSinD(T1+Y) + 62.0*RSinD(2.0*L+T1) -
- 33.0*RSinD(T1-Y-L) - 32.0*RSinD(T1-2.0*L) - 30.0*RSinD(L1+T1-Y);
- *moonla = MB =
- RSgn(MB)*((RAbs(MB)/M)/rDegMax-RFloor((RAbs(MB)/M)/rDegMax))*rDegMax;
-
- /* Compute position of the North Lunar Node, either True or Mean. */
-
- if (us.fTrueNode)
- N = N+5392.0*RSinD(2.0*T1-Y)-541.0*RSinD(L1)-442.0*RSinD(Y)+
- 423.0*RSinD(2.0*T1)-291.0*RSinD(2.0*L-2.0*T1);
- *nodelo = Mod(N/M+is.rSid);
- *nodela = 0.0;
- }
- #endif /* MATRIX */
-
- /* matrix.c */
-